/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package edu.uoc.tfc.exuoc.controladors;

/**
 *
 * @author Emili A.
 */


import edu.uoc.tfc.exuoc.errors.LlistatDAOException;
import edu.uoc.tfc.exuoc.model.Arxiu;
import edu.uoc.tfc.exuoc.config.Config;
import edu.uoc.tfc.exuoc.errors.BuitException;
import edu.uoc.tfc.exuoc.errors.EliminarIOException;
import edu.uoc.tfc.exuoc.utils.Eines;


import java.io.File;
import java.net.*;
import java.util.Iterator;
import java.util.ArrayList;
import org.hibernate.HibernateException;



public class GestorArxiuDades implements InterfaceGestor{

    private static GestorArxiuDades INSTANCE = null;
    private GestorLogs  log=null;
    private Arxiu entitat= new Arxiu();
    private File file=null;


    public GestorArxiuDades() {
        entitat= new Arxiu(Config.valorNullStr,Config.valorNullStr,
                            Config.valorNullStr,Config.valorNullInt);
        file=null;
        log=GestorLogs .getLogger(this.getClass().getName());
    }

    //Genera les dades per l'objecte Arxiu partint de les dades de l'objecte File
    //Per generar o guardar els arxius s'ha d'indicar expressament.
    public GestorArxiuDades(File f){
        log=GestorLogs .getLogger(this.getClass().getName());
        this.inicialitzar(f);
    }

    // creador sincronizado para protegerse de posibles problemas  multi-hilo
    // otra prueba para evitar instantiación múltiple
    private synchronized static void createInstance() {
        if (INSTANCE == null) {
            INSTANCE = new GestorArxiuDades();
        }

    }
    public static GestorArxiuDades getInstance() {
        if (INSTANCE == null) createInstance();
            return INSTANCE;
    }

    /**
     * Es prepara el gestor amb el fitxer indicat i s'inicialitza l'entitat.
     * @param f
     */
    public void inicialitzar(File f){

        file=f;
        if (f.exists()){
        //S'assignem els valors originals subministrats per l'struts Upload
        entitat=new Arxiu(this.getNom(),this.getTipus(), this.getUbicacio(),
                            this.getMida());
        }else{
            entitat= new Arxiu(Config.valorNullStr,Config.valorNullStr,
                            Config.valorNullStr,Config.valorNullInt);
        }
    }

    public void inicialitzar (Arxiu arxi){
     File f =new File(arxi.getUbicacio(),arxi.getNom());
     this.inicialitzar(f);

    }

    public boolean Exists(){
        return this.file.exists();
    }

    private void setEntitat(Arxiu entitat) {
        this.entitat = entitat;
    }

    public Arxiu getEntitat() {
        return entitat;
    }

        /**
     *
     * @return el tipus de l'objecte File.
     */
    private  String getTipus(){

        // 14:01:11:Emili: No funciona return new MimetypesFileTypeMap().getContentType(file);

        String tipus=Config.valorNullStr;
        try {
            URL u = new URL("file://"+file.getCanonicalPath());
            URLConnection uc = null;
            uc = u.openConnection();
            tipus = uc.getContentType();

        } catch (Exception ex) {
            this.log.error("GAD:getTipus: Error consultant el tipus."
                    +ex.getLocalizedMessage());
        }
        return tipus;

    }

    /**
     *
     * @param arxiu Fitxer a consultar
     * @return mida de l'arxiu en KiloBytes
     */
    private  int getMida(){

        return ((int)(file.length()/(1024))) ;
    }

    private  String getUbicacio(){
        int pos=0;
        String ubicacio=Config.valorNullStr;

        pos=file.getAbsolutePath().lastIndexOf(File.separator);
        if (pos >0 )
            ubicacio=file.getAbsolutePath().substring(0, pos)
                    .concat(File.separator);
        return ubicacio;
    }

    private  String getNom(){

        return file.getName();
    }

    /**
     *  Un cop assignat el file aquest mètode guarda l'arxiu a la carpeta de 
     * fitxers temporal del dipòsit i deixa l'objecte Arxiu generat a entitat.
     * Cas de que tot el procés de creaciḉo de l'ítem sigui correcta llavors cal
     * fer servir el mètode ubicarArxiu, el qual mourà l'arxiu del dir temporal
     * a l'ubuació definitiva del dipòsit
     * @param nom
     * @param tipus, tipus de l'arxiu en format MIMEType
     */
    public void generarArxiu(String nom,String tipus){

        if (this.crearArxiu(this.file,nom)){
            entitat=new Arxiu(nom,tipus,this.getUbicacio(),
                            this.getMida() );
        }

    }

    private boolean crearArxiu(File f, String nomArxiu){
        boolean correcte=true;
        try{

            //Es comprova el directori temporal
            File dir= new File(Config.rutaFitxersTemp);
            if (! dir.exists()) correcte=dir.mkdir();
            if (!correcte) return correcte;
            dir=null;
            File guardarArxiu =new File(Config.rutaFitxersTemp,nomArxiu);
            int i=0;

            //Comprovem que no existeix un d'igual. si és així el renombrem
            while(guardarArxiu.exists()){
                guardarArxiu =new File(Config.rutaFitxersTemp,i+"_"+nomArxiu);
                i++;
            }
            file.renameTo(guardarArxiu);

            //Assignem el nou objecte al declarat a la classe
            this.file=guardarArxiu;
        }catch(Exception e){
            this.log.error("GAD:crearArxiu:Fallada a la creació de l'arxiu "
                    +"de dades."+e.getLocalizedMessage());
            correcte=false;
        }
        return correcte;
    }

      public Arxiu eliminarArxiu() {
        Arxiu perEliminar=null;

            if (! this.file.delete() )
                this.log.error("GAD:eliminarArxiu:No s'ha pogut eliminar: "+
                 this.entitat.getNom());
            else{

                perEliminar=this.entitat;
            }

        return perEliminar;
    }
      /**
       * Mètode que té per funció col.locar l'arxiu ubicat al directori temporal
       * al seu lloc definitiu dintre del dipòsit per què sigui accessible via web
       * @return true si s'ha fet el canvi
       */
      public boolean UbicarArxiu(){
          boolean mogut=true;
          //Tenim un arxiu guardat. si cert llavors sabrem com es diu
          if ( !(this.getEntitat().getNom().equals(Config.valorNullStr) &&
                  file!=null) ){
              try{
                // Directori destí
                File dir = new File(Config.rutaFitxers);

                // Es mou l'arxiu a la nova ubicació
                mogut = file.renameTo(new File(dir, file.getName()));
                if (mogut) {
                    //Es modifica la ubicació de l'entitat
                    this.getEntitat().setUbicacio(Config.rutaFitxers);
                }
              }catch(Exception ex){
                  getLog().error("GAD:UbicarArxiu: no s'ha pogut moure l'arxiu:"
                          +getEntitat().getNom()+" a l'ubicació definitiva."
                          +ex.getLocalizedMessage() );
              }
          }
          return mogut;
      }

    @Override
    public void openGestor() {

        this.log.error("GAD:openGestor:funció no implementada");
    }

    @Override
    public void tancar() {
        this.file=null;
        this.entitat=null;
        this.log.error("GAD:tancar:funció no implementada");
    }

   @Override
    public GestorLogs  getLog() {
        return log;
    }

    @Override
    public void setLog(GestorLogs  log) {
        this.log = log;
    }

    @Override
    public int num() throws HibernateException, BuitException {
        this.log.error("GAD:num:funció no implementada");
        return Config.valorNullInt;
    }

    @Override
    public int num(String nomCercat) throws HibernateException, BuitException {
        this.log.error("GAD:num:funció no implementada");
        return Config.valorNullInt;
    }

    @Override
    public Iterator<?> llistat() throws LlistatDAOException, BuitException {
        this.log.error("GAD:llistat:funció no implementada");
        return new ArrayList(0).iterator();
    }

    @Override
    public Iterator<?> llistat(int ini, int fi) throws LlistatDAOException
            , BuitException {
        this.log.error("GAD:llistat:funció no implementada");
        return new ArrayList(0).iterator();
    }

    @Override
    public Iterator<?> llistat(String camp, String pernom, int ini, int fi)
            throws LlistatDAOException, BuitException {
        this.log.error("GAD:llistat:funció no implementada");
        return new ArrayList(0).iterator();
    }

  public static void main(String []args){
        GestorArxiuDades gad= new GestorArxiuDades();
        File fil = new File("/bin/mount.jpg");

        gad.inicialitzar(fil);

        Eines.escriu(gad.Exists());

        Eines.escriu(gad.getTipus());

        fil=null;
        gad=null;
    }

}
